package sim16;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

/**
 * 
 */

/**
 * The register file class. Initialized by constructor by reading from a passed file.
 * Supports reading and writing to registers. Includes fixed register 0.
 * @author Piotr
 *
 */
public class RegisterFile {
	
	final static int regFileSize = 32;
	private int[] regFile;
	
	/**
	 * Creates a register file initialized to all zeros.
	 */
	RegisterFile() {
		regFile = new int[regFileSize];
		for (int ii = 0; ii < regFileSize; ii++) {
			regFile[ii] = 0;
		}
	}
	
	
	/**
	 * Creates a new register file and initializes it using the initialization file.
	 * @param init	file containing the initialization data.
	 * @throws FileNotFoundException 
	 */
	RegisterFile(File init) throws FileNotFoundException {
		regFile = new int[regFileSize];
		for (int ii = 0; ii < regFileSize; ii++) {
			regFile[ii] = 0;
		}
		Scanner scin = new Scanner(init);
		Scanner scline;
		String line;
		while (scin.hasNext()) {			// Add some safety checks here
			line = scin.nextLine();
			scline = new Scanner(line);
			String temp = scline.findInLine("^r\\d+");
			if (temp != null) {
				int index = new Integer(temp.substring(1, temp.length()));
				if (scline.hasNextInt()) {
					regFile[index] = scline.nextInt(10);
				}
			}	
		}
	}
	
	/**
	 * Reads a value from the register file indexed by index. If index is out of bounds of the register file,
	 * then an RegisterIndexOutOfBoundsException is thrown.
	 * @param index
	 * @return the value in the register
	 * @throws RegisterIndexOutOfBoundsException
	 */
	int readReg(int index) throws RegisterIndexOutOfBoundsException {
		if (index >= 0 && index < regFileSize) {
			return regFile[index];
		} else {
			throw new RegisterIndexOutOfBoundsException(index);
		}
		
	}
	
	/**
	 * Writes a value to the register file. If writing to register 0, nothing happens. If writing to
	 * a register index that is out of bounds of the register file, an RegisterIndexOutOfBoundsException
	 * is thrown.
	 * @param index the index of the register file
	 * @param value the value to be written to the array
	 * @throws RegisterIndexOutOfBoundsException thrown if index is out of bounds
	 */
	void writeReg(int index, int value) throws RegisterIndexOutOfBoundsException {
		if (index >= 0 && index < regFileSize) {
			if (index > 0) {
				regFile[index] = value;
			}
		} else {
			throw new RegisterIndexOutOfBoundsException(index);
		}
	}
	
	/**
	 * Returns the string representation of the register file.
	 */
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("######################## Register File ########################");
		sb.append("\nRegister\tValue");
		for(int i = 0; i < regFileSize; i++) {
			sb.append("\nr" + i + "\t\t" + regFile[i]);
		}
		sb.append("\n");
		return sb.toString();
	}
	
}
